﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SceneEngine
{
    public class TerrainEffect : Effect
    {
        #region Properties
        private EffectParameter worldViewProjParam;

        public Matrix WorldViewProj
        {
            get { return worldViewProjParam.GetValueMatrix(); }
            set { worldViewProjParam.SetValue(value); }
        }

        private EffectParameter worldParam;

        public Matrix World
        {
            get { return worldParam.GetValueMatrix(); }
            set { worldParam.SetValue(value); }
        }

        private EffectParameter viewParam;

        public Matrix View
        {
            get { return viewParam.GetValueMatrix(); }
            set { viewParam.SetValue(value); }
        }

        private EffectParameter[] textureParams;

        internal EffectParameter[] TextureParams
        {
            get { return textureParams; }
            set { textureParams = value; }
        }

        private EffectParameter[] textureScaleParams;

        internal EffectParameter[] TextureScaleParams
        {
            get { return textureScaleParams; }
            set { textureScaleParams = value; }
        }

        private EffectParameter colormapParam;

        internal Texture2D Colormap
        {
            get { return colormapParam.GetValueTexture2D(); }
            set { colormapParam.SetValue(value); }
        }

        private EffectParameter normalMapParam;

        internal Texture2D NormalMap
        {
            get { return normalMapParam.GetValueTexture2D(); }
            set { normalMapParam.SetValue(value); }
        }

        private EffectParameter groundCursorPositionParam;

        internal Vector3 GroundCursorPosition
        {
            get { return groundCursorPositionParam.GetValueVector3(); }
            set { groundCursorPositionParam.SetValue(value); }
        }

        private EffectParameter groundCursorTexParam;

        internal Texture2D GroundCursorTex
        {
            get { return groundCursorTexParam.GetValueTexture2D(); }
            set { groundCursorTexParam.SetValue(value); }
        }

        private EffectParameter groundCursorSizeParam;

        internal float GroundCursorSize
        {
            get { return groundCursorSizeParam.GetValueSingle(); }
            set { groundCursorSizeParam.SetValue(value); }
        }

        private EffectParameter cameraPositionParam;

        internal Vector3 CameraPosition
        {
            get { return cameraPositionParam.GetValueVector3(); }
            set { cameraPositionParam.SetValue(value); }
        }

        private EffectParameter cameraDirectionParam;

        internal Vector3 CameraDirection
        {
            get { return cameraDirectionParam.GetValueVector3(); }
            set { cameraDirectionParam.SetValue(value); }
        }

        private EffectParameter lightDirection;

        internal Vector3 LightDirection
        {
            get { return lightDirection.GetValueVector3(); }
            set { lightDirection.SetValue(value); }
        }

        private EffectParameter ambientLightParam;

        internal Vector3 AmbientLight
        {
            get { return ambientLightParam.GetValueVector3(); }
            set { ambientLightParam.SetValue(value); }
        }

        private EffectParameter lightPowerParam;

        internal float LightPower
        {
            get { return lightPowerParam.GetValueSingle(); }
            set { lightPowerParam.SetValue(value); }
        }

        private bool drawCursor = true;
        private EffectParameter drawCursorParam;

        public bool DrawCursor
        {
            get { return drawCursor; }
            set 
            {
                drawCursor = value;
                drawCursorParam.SetValue(value); 
            }
        }


        private EffectTechnique texturedTechnique;

        internal EffectTechnique TexturedTechnique
        {
            get { return texturedTechnique; }
            set { texturedTechnique = value; }
        }

        #endregion

        public TerrainEffect(Effect cloneSource)
            : base(cloneSource)
        {
            InitializeComponent();

            CurrentTechnique = texturedTechnique;
            World = Matrix.Identity;
        }

        private void InitializeComponent()
        {
            texturedTechnique = Techniques["TransformTexture"];

            this.worldViewProjParam = Parameters["WorldViewProj"];
            this.worldParam = Parameters["World"];
            this.viewParam = Parameters["View"];

            TextureParams = new EffectParameter[5];
            textureScaleParams = new EffectParameter[5];
            for (int i = 0; i < TextureParams.Length; i++)
            {
                TextureParams[i] = Parameters["t" + i];
                textureScaleParams[i] = Parameters["t" + i + "scale"];
            }

            this.colormapParam = Parameters["colormap"];
            this.normalMapParam = Parameters["normalMap"];
            this.groundCursorPositionParam = Parameters["groundCursorPosition"];
            this.groundCursorTexParam = Parameters["groundCursorTex"];
            this.groundCursorSizeParam = Parameters["groundCursorSize"];
            this.cameraPositionParam = Parameters["cameraPosition"];
            this.cameraDirectionParam = Parameters["cameraDirection"];
            this.lightDirection = Parameters["lightDirection"];
            this.ambientLightParam = Parameters["ambientLight"];
            this.lightPowerParam = Parameters["lightPower"];
            this.drawCursorParam = Parameters["drawCursor"];
        }

        public void SetTexture(int channel, Texture2D texture)
        {
            textureParams[channel].SetValue(texture);
        }
        public void SetUVScale(int channel, float scale)
        {
            textureScaleParams[channel].SetValue(scale);
        }

        public override Effect Clone()
        {
            return new TerrainEffect(this);
        }
    }
}
